﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;

using DotSpatial.Symbology;

using DotSpatial.Topology;

using Point = System.Drawing.Point;


namespace HaGisPack
{
    class SelectAndMoveMF : DotSpatial .Controls.MapFunctionSelect 
    {


        public SelectAndMoveMF(IMap map, List<IFeatureLayer> LayerList)
            : base(map)
        {
            this._LayerList = LayerList;
            this.FunctionBase = new FMapFunctionBase(map);
            this.Configure();
        }

        private void Configure()
        {
            this._selectedFeaturesID = new List<string>();
        }

        //所有图层
        private List<IFeatureLayer> _LayerList;

        private FMapFunctionBase _FunctionBase;

        public FMapFunctionBase FunctionBase
        {
            get { return _FunctionBase; }
            set { _FunctionBase = value; }
        }



        # region 字段

        private bool _dragging; //选择标志
        private bool _Movedragging; //移动中标志
        private bool _UseMove = false;  //可移动标志

        private bool _IsCopy = false;  //复制文件标志

        private Point _mousePosition;

        private List<string> _selectedFeaturesID;

        private Point _dragCoord; //选择、移动时的起始坐标


        # endregion

        # region 属性

        /// <summary>
        /// 选择的所有图形
        /// </summary>
        public List<string> SelectedFeatures
        {
            get { return this._selectedFeaturesID; }
            set { this._selectedFeaturesID = value; }
        }


        # endregion




        # region 方法


        private IFeature GetFeature( string featureID )
        {
            IFeature f;
            foreach (IFeatureLayer flay in this._LayerList)
            {
                foreach (IFeature feature in (flay.DataSet as IFeatureSet).Features)
                {
                    if ((feature.DataRow["id"] as string) == featureID)
                    {
                        f = feature;
                        return f;
                    }
                }
            }
            return null;
        }


        protected override void OnDraw(MapDrawArgs e)
        {
            //if (_dragging == false) return;
            //if (_dragCoord == null) return;

            if (_dragging == true && _dragCoord != null) //处于选择状态
            {
                base.OnDraw(e);
            }

            if (this._Movedragging == true && this._dragCoord != null)  //处于移动状态
            {
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

                GraphicsPath gp = new GraphicsPath();
                Pen Blue = new Pen(Color.Blue, 2);


                foreach (string featureID in this._selectedFeaturesID)  //每个图层的每个Shape(Feature)
                {

                    IFeature f = this.GetFeature(featureID);  //根据ID找到已选择的图形
                                        
                    if (f == null) return;

                    
                    List<Point> pts = new List<Point>();

                    foreach (Coordinate c in f.Coordinates)
                    {
                        Point pt = new Point();
                        pt.X = Map.ProjToPixel(c).X - this._dragCoord.X + this._mousePosition.X;
                        pt.Y = Map.ProjToPixel(c).Y - this._dragCoord.Y + this._mousePosition.Y;
                        pts.Add(pt);
                    }

                    if (f.FeatureType == FeatureType.Point)
                    {
                        gp.AddRectangle(new Rectangle(pts[0].X - 1, pts[0].Y - 1, 2, 2));
                    }

                    if (f.FeatureType == FeatureType.Line)
                    {
                        //e.Graphics.DrawLines(Blue, pts.ToArray());

                        GraphicsPath gp1 = new GraphicsPath();
                        gp1.AddLines(pts.ToArray());//先将直线填进一个GraphicsPath
                        gp.AddPath(gp1, false);   //再将这个GraphicsPath添加到另一个GraphicsPath，false表示两个直线之间没有关系
                    }
                    if (f.FeatureType == FeatureType.Polygon)
                    {
                        gp.AddPolygon(pts.ToArray());
                    }

                }
                //Feature更新
                //fl.DataSet.InitializeVertices();
                //fl.DataSet.UpdateEnvelopes();


                e.Graphics.DrawPath(Blue, gp);

                Blue.Dispose();
                gp.Dispose();

                //map更新
                Map.Invalidate();
                Map.MapFrame.Initialize();
            }
                       

        }


        //==================继承了自带的Select,这两个方法没用了==========================

        /// <summary>
        /// 使鼠标经过的和选中的Shape亮起来
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        //private bool ShapeHighlight()
        //{

        //    Rectangle SelectRect = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_mousePosition.Y - _dragCoord.Y));
        //    IEnvelope ext = Map.PixelToProj(SelectRect).ToEnvelope();
        //    IPolygon env = ext.ToPolygon();

        //    bool requiresInvalidate = false;

        //    foreach (IFeatureLayer fl in this._LayerList)
        //    {
        //        IFeatureSet _featureSet = fl.DataSet;
        //        foreach (IFeature feature in _featureSet.Features)
        //        {
        //            if (_featureSet.FeatureType == FeatureType.Point)
        //            {
        //                MapPointLayer mpl = fl as MapPointLayer;

        //                if (mpl != null)
        //                {
        //                    if (ext.Contains(feature.Coordinates[0]))  //本句判断是不是选择的这个Feature，以下代码用来表现选择的Feature
        //                    {

        //                        IFeatureCategory oldCategory = mpl.GetCategory(feature);
        //                        this._activeFeatures.Add(feature, oldCategory);

        //                        IFeatureCategory selectedCategory = new PointCategory();

        //                        selectedCategory.CopyProperties(oldCategory);  //这一句不一样???
        //                        selectedCategory.SetColor(Color.FromArgb(255, 0, 0));
        //                        selectedCategory.LegendItemVisible = false;

        //                        mpl.SetCategory(feature, selectedCategory);

        //                        //mpl.SetCategory(_activeFeature[_activeFeature.Count - 1], _selectedCategory);  //选中Feature后，改变一下类型
        //                    }
        //                }
        //                requiresInvalidate = true;
        //            }
        //            else
        //            {
        //                if (feature.Intersects(env))  //本句判断是不是选择的这个Feature，以下代码只是用来表现此Feature与其它Feature的不同
        //                {

        //                    IFeatureCategory oldCategory = fl.GetCategory(feature);
        //                    this._activeFeatures.Add(feature, oldCategory);

        //                    IFeatureCategory newCategory = oldCategory;

        //                    if (_featureSet.FeatureType == FeatureType.Polygon)
        //                    {
        //                        //newCategory = oldCategory as PolygonCategory;

        //                        newCategory = new PolygonCategory(Color.FromArgb(55, 255, 0, 0), Color.Red, 1);
        //                        newCategory.LegendItemVisible = false;



        //                    }
        //                    if (_featureSet.FeatureType == FeatureType.Line)
        //                    {
        //                        //newCategory = oldCategory as LineCategory;

        //                        newCategory = new LineCategory(Color.Red, 3);
        //                        newCategory.LegendItemVisible = false;

        //                    }

        //                    fl.SetCategory(feature, newCategory);     //这个_activeCategory与_selectedCategory作用一样，类型一样，为什么要写成两个？？？？                    

        //                }

        //            }

        //        }
        //    }

        //    return requiresInvalidate;

        //}
        
        /// <summary>
        /// 鼠标离开Shape后，Shap要恢复正常
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        //public void ShapeRemoveHighlight()
        //{
        //    if (this._selectedFeatures == null || this._selectedFeatures.Count == 0) return; //没有Shape被点亮


        //    //有Shape被点亮，则将点亮的Shape赋回原来的类型

        //    //bool requiresInvalidate = false;

        //    foreach (IFeatureLayer fl in this._LayerList)
        //    {
        //        IFeatureSet fs = fl.DataSet as IFeatureSet;

        //        foreach (IFeature f in fs.Features)
        //        {
        //            if (this._activeFeatures.ContainsKey(f) == true)
        //            {
        //                fl.SetCategory(f, _activeFeatures[f]);
        //            }
        //        }
        //    }

        //    this._activeFeatures.Clear();
        //    this._selectedFeatures.Clear();

        //    Map.MapFrame.Initialize();
        //    Map.Invalidate();

        //}

        //============================================================================

        protected override void OnMouseMove(GeoMouseArgs e)
        {
            _mousePosition = e.Location;

            if (this._Movedragging == false)  //不在移动状态
            {

                //如果已经选择了Feature
                if (this._selectedFeaturesID != null && this._selectedFeaturesID.Count > 0)
                {
                    Rectangle mouseRect = new Rectangle(_mousePosition.X - 3, _mousePosition.Y - 3, 6, 6);
                    IEnvelope ext = Map.PixelToProj(mouseRect).ToEnvelope();
                    IPolygon env = ext.ToPolygon();


                    //当鼠标经过任意一个已选的Feature的时候，鼠标变为Hand,可移动状态
                    foreach (string id in this._selectedFeaturesID)
                    {
                        IFeature f = this.GetFeature(id);   //根据ID找到已选择的图形
                                             
                       

                        if (f == null) return;

                        
                        if (f.FeatureType == FeatureType.Point)
                        {
                            if (ext.Contains(f.Coordinates[0]))
                            {
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = true; //变成可移动状态
                                break;
                            }
                            else
                            {
                                //this.Map.Cursor = new Cursor(@"F:\MapWindow6\mapwindow6_dbc476e1b259\MapWindow6Orlando\Resources\select.ico");
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = false;
                            }
                        }
                        else
                        {
                            if (f.Intersects(env))
                            {
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = true;  //变成可移动状态
                                break;
                            }
                            else
                            {
                                //this.Map.Cursor = new Cursor(@"F:\MapWindow6\mapwindow6_dbc476e1b259\MapWindow6Orlando\Resources\select.ico");
                                this.Map.Cursor = Cursors.Hand;
                                this._UseMove = false;
                            }
                        }
                    }
                }
            }
            else  //在移动状态
            {
                this.Map.Cursor = Cursors.Hand;
            }

            Rectangle invilid = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_dragCoord.Y - _mousePosition.Y));
            invilid.Inflate(20, 20);
            Map.Invalidate(invilid);
            base.OnMouseMove(e);

        }

        protected override void OnMouseDown(GeoMouseArgs e)
        {

            Map.MapFrame.Initialize();
            Map.Invalidate();

            if (this._UseMove == false) //不在可移动状态，在选择状态
            {                
                _dragging = true;

                this._selectedFeaturesID.Clear();
                this._selectedFeaturesID = new List<string>();

                foreach (IFeatureLayer fl in this._LayerList)
                {
                    fl.Selection.Clear();  //清空已选
                }

                base.OnMouseDown(e);  //使用自带的Select的OnMouseDown
               
            }
            else  //在可移动状态
            {
                if (e.Button == MouseButtons.Right) return;
                this._Movedragging = true;  //状态变为移动状态
            }

            _dragCoord = e.Location;

        }

        

        protected override void OnMouseUp(GeoMouseArgs e)
        {
            //只要是MouseUp,选择和移动都结束

            if (_dragging == true)
            {
                _dragging = false; //选择结束
                base.OnMouseUp(e);  //自带的Select的OnMouseUp


                if (this._selectedFeaturesID.Count == 0)  //这个if是为了解决双击标题栏而引起的MouseUp事件的Bug
                {
                    foreach (IFeatureLayer fl in this._LayerList)
                    {
                        foreach (IFeature f in fl.Selection.ToFeatureList())
                        {
                            this._selectedFeaturesID.Add(f.DataRow["id"] as string);  //存储所选图形的ID
                           
                        }
                    }
                    if (this._FunctionBase.Parent.SelectedID == null)
                    {
                        this._FunctionBase.Parent.SelectedID = new List<string>();
                    }
                    this._FunctionBase.Parent.SelectedID.Clear();
                    this._FunctionBase.Parent.SelectedID.AddRange(this._selectedFeaturesID.ToArray()); //外部存储所选图形的ID
                }
            }

            if (this._Movedragging == true)
            {
                this._Movedragging = false; //移动结束

                foreach (string featureID in this._selectedFeaturesID)
                {

                    IFeature f = this.GetFeature(featureID); //根据ID找到已选择的图形
                                   

                    if (f == null) return;

                    List<Coordinate> newcoors = new List<Coordinate>();

                    //设置当前图层，这一句是必须有的……因为现在是多图层选择！！！！！！！！！！
                    this ._FunctionBase .Parent.Parent.LayerSys.SetCurrentLayer(f.ParentFeatureSet.DataTable.TableName);
                    //得到已选择的、要移动的shp
                    FShape OldShp = (this._FunctionBase.Parent.Parent.LayerSys.CurrentLayer as FShapeLayer).GetShapeByID(f.DataRow["id"].ToString());

                    //因为是引用传递，将旧的Shp的所有属性赋给新的shp,不能直接等于！
                    FShape NewShp;
                    if (this._IsCopy == false)  //移动
                    {
                        NewShp = new FShape(OldShp.Id);
                    }
                    else  //复制
                    {
                        int i = 1;

                        //string id = OldShp.Id + "副本";
                        string id = OldShp.Id;

                        //foreach (IFeature feature in (this._FunctionBase.Parent.Parent.LayerSys.CurrentLayer.DataSet as IFeatureSet).Features)
                        //{
                        //    if (feature.DataRow["id"].ToString().Length >id.Length && feature.DataRow["id"].ToString().Substring(0, id.Length)==id)
                        //    {
                        //        i++;
                        //    }
                        //}

                        //id = id + i.ToString();
                        NewShp = new FShape(id);
                    }

                    //赋坐标
                    foreach (Coordinate c in OldShp.normalPts)
                    {
                        Coordinate coor = new Coordinate(c.X, c.Y);
                        NewShp.normalPts.Add(coor);
                    }
                    foreach (Coordinate c in OldShp.KeyPts)
                    {
                        Coordinate coor = new Coordinate(c.X, c.Y);
                        NewShp.KeyPts.Add(coor);
                    }
                    NewShp.LayerName = OldShp.LayerName; //层名称

                    //赋完旧的属性后，修改自定义Fshape移动后的坐标
                    foreach (Coordinate c in NewShp.normalPts)
                    {
                        c.X = c.X + Map.PixelToProj(this._mousePosition).X - Map.PixelToProj(this._dragCoord).X;
                        c.Y = c.Y + Map.PixelToProj(this._mousePosition).Y - Map.PixelToProj(this._dragCoord).Y;
                    }

                    //本来关键点也应该修改坐标的，但是normalPts与关键点之间也是引用传递的关系，所以不能修改
                    //不知道是不是应该把normalPts与关键点分开，不应是引用传递的相等的关系？？？？？？？？？？
                    //foreach (Coordinate c in NewShp.KeyPts)
                    //{
                    //    c.X = c.X + Map.PixelToProj(this._mousePosition).X - Map.PixelToProj(this._dragCoord).X;
                    //    c.Y = c.Y + Map.PixelToProj(this._mousePosition).Y - Map.PixelToProj(this._dragCoord).Y;
                    //}

                    if (this._IsCopy == false)  //移动
                    {
                        this.FunctionBase.OnShapeChanged(NewShp);
                    }
                    else
                    {
                        this.FunctionBase.OnShapeCopyed (NewShp);                        
                    }
                }

                this._IsCopy = false;  //所有完成后,复制都为False

                //Feature更新
                foreach (IFeatureLayer fl in this._LayerList)
                {
                    fl.DataSet.InitializeVertices();
                    fl.DataSet.UpdateExtent();
                }
            }
            
            Map.MapFrame.Initialize();

        }


        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                if (this._Movedragging == true)  //如果正在移动
                {
                    this._Movedragging = false; //结束移动

                    //Feature更新
                    //foreach (IFeatureLayer fl in this._LayerList)
                    //{
                    //    fl.DataSet.InitializeVertices();
                    //    fl.DataSet.UpdateEnvelopes();
                    //}
                }

                if (this._dragging == true)
                {
                    this._dragging = false;  //结束选择
                    this.Map.Invalidate();
                    this.Map.MapFrame.Initialize();
                }

            }

            if (e.KeyCode == Keys.Delete)
            {
                base.OnKeyDown(e);

                foreach (string featureID in this._selectedFeaturesID)
                {
                    IFeature f = this.GetFeature(featureID); //根据ID找到已选择的图形
                                      

                    if (f == null) return;

                   
                    this._FunctionBase.Parent.Parent.LayerSys.SetCurrentLayer(f.ParentFeatureSet.DataTable.TableName);
                    //得到已选择的shp
                    FShape OldShp = (this._FunctionBase.Parent.Parent.LayerSys.CurrentLayer as FShapeLayer).GetShapeByID(f.DataRow["id"].ToString());

                    this.FunctionBase.OnShapeRemoved(OldShp);

                    this.Map.Invalidate();
                    this.Map.MapFrame.Initialize();
                } 
                this._selectedFeaturesID.Clear();
                this._FunctionBase.Parent.SelectedID.Clear();  //清空所选图形的ID

            }

            if (e.KeyCode == Keys.ControlKey)
            {
                this._IsCopy = true;
            }

            
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            if (e.KeyCode == Keys.ControlKey)
            {
                this._IsCopy = false;
            }
           
        }


        protected override void OnMouseWheel(GeoMouseArgs e)
        {
            base.OnMouseWheel(e);

            Rectangle r = e.Map.MapFrame.View;
            int w = r.Width;
            int h = r.Height;

            int scale = 5;

            if (e.Delta < 0)
            {
                r.Inflate(r.Width / (2 * scale), r.Height / (scale * 2));
                r.X += w / (2 * scale) - e.X / (scale);
                r.Y += h / (2 * scale) - e.Y / (scale);
                e.Map.MapFrame.View = r;
                e.Map.MapFrame.ResetExtents();
            }
            else
            {
                r.Inflate(-r.Width / (4 * scale), -r.Height / (4 * scale));
                // The mouse cursor should anchor the geographic location during zoom.
                r.X += (e.X / (2 * scale)) - w / (4 * scale);
                r.Y += (e.Y / (2 * scale)) - h / (4 * scale);
                e.Map.MapFrame.View = r;
                e.Map.MapFrame.ResetExtents();
            }
           
        }


        # endregion







    }
}

